#pragma once
#include <iostream>
#include <ctime>
#include <thread>
#include <cstdio>

enum LogLevel
{
    LINF = 0,
    LDBG,
    LERR
};

static int defaultLevel = LINF;

#define LOG(level, format, ...) do\
    {\
        if(level < defaultLevel) break;\
        time_t t = time(NULL);\
        struct tm *ltm = localtime(&t);\
        char tmp[32] = {0};\
        strftime(tmp, 31, "%H:%M:%S", ltm);\
        fprintf(stdout, "[%p %s %s:%d] " format "\n", (void*)pthread_self(),tmp, __FILE__, __LINE__, ##__VA_ARGS__);\
    }while(0)

#define INF_LOG(format, ...) LOG(LINF, format, ##__VA_ARGS__)
#define DBG_LOG(format, ...) LOG(LDBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(LERR, format, ##__VA_ARGS__)


class Any
{
private:
    class holder
    {
    public:
        virtual ~holder(){}
        virtual const std::type_info& type() = 0;
        virtual holder *clone() = 0;
    };
    template<class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T &val) : _val(val)
        {}
        virtual ~placeholder(){}
        //获取子类对象保存的数据类型
        virtual const std::type_info& type() override {return typeid(T);}
        //针对当前对象，克隆新的子类对象
        virtual holder *clone() override {return new placeholder<T>(_val);}

    public:
        T _val;
    };
    holder *_content;

private:
    void swap(Any& other) noexcept 
    {
        std::swap(this->_content, other._content);
    }
public:
    Any():_content(nullptr)
    {}
    template<class T>
    Any(const T &val) : _content(new placeholder<T>(val))
    {}
    Any(const Any &other):_content(other._content ? other._content->clone() : nullptr)
    {}
    Any(Any&& other) : _content(other._content) 
    {
        other._content = nullptr; 
    }
    ~Any()  {delete _content;}

    template<class T>
    T* get()
    {
        //类型校验
        if(_content && typeid(T) == _content->type())
        {
            auto ptr = dynamic_cast<placeholder<T>*>(_content);
            if(ptr != nullptr)
                return &(ptr->_val);          
        }
        return nullptr;
    }
    template<class T>
    Any& operator=(const T &val)
    {
        Any tmp(val);
        swap(tmp);
        return *this;
    }
    Any& operator=(const Any &other)
    {
        Any tmp(other);
        swap(tmp);
        return *this;
    }
};
